#include <pthread.h>

struct msg {
	struct msg* m_next;
	char* str;
};

int id = 0;
struct msg * workq = NULL;
pthread_cond_t qready = PTHREAD_COND_INITIALIZER;
pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;

void process_msg(void)
{
	struct msg *mp;
	for(;;)
	{
		pthread_mutex_lock(&qlock);
		while(workq == NULL)
			pthread_cond_wait(&qready, &qlock);
		mp = workq;
		workq = mp->m_next;
		pthread_mutex_unlock(&qlock);

		/* now process the message mp */
		printf("process message : %s\n", mp->str);
		printf("free str at 0x%x\n", (unsigned int)(mp->str));
		free(mp->str);
		printf("free mp at 0x%x\n", (unsigned int)mp);
		free(mp);
	}
}

void enqueue_msg(struct msg* mp)
{
	pthread_mutex_lock(&qlock);
	mp->m_next = workq;
	workq = mp;
	snprintf(mp->str, 32, "Scarborough %d", id++);
	printf("enqueue message : %s\n", mp->str);
	pthread_mutex_unlock(&qlock);
	pthread_cond_signal(&qready);
}

void* foo(void* arg)
{
	pthread_t tid = pthread_self();
	printf("thread %u start.\n", (unsigned int)tid);
	int i = 0;
	struct msg* mp;
	for(; i < 100; ++i)
	{
		mp = (struct msg*)malloc(sizeof(struct msg));
		mp->str = (char*)malloc(32);
		enqueue_msg(mp);
		sleep(1);
	}
	printf("thread %u end.\n", (unsigned int)tid);
}

int main()
{
	int i;
	pthread_t tid;
	for (i = 0; i < 5; ++i)
	{
		pthread_create(&tid, NULL, foo, NULL);
	}
	process_msg();
	return 0;
}

